﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace OverSizeImage
{
    public class VerticalTick : UserControl
    {
        Pen backpen;
        const int rulerWidth = 30;
        double scaleDefaultValue = 5;
        double scaleMinPx = 10;
        double scaleMaxPx = 100;



        public double ScaleValue
        {
            get { return (double)GetValue(ScaleValueProperty); }
            set { SetValue(ScaleValueProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ScaleValue.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ScaleValueProperty =
            DependencyProperty.Register("ScaleValue", typeof(double), typeof(VerticalTick), new PropertyMetadata(1.0, new PropertyChangedCallback(RefeshTick)));

        public double PxToMM
        {
            get { return (double)GetValue(PxToMMProperty); }
            set { SetValue(PxToMMProperty, value); }
        }

        // Using a DependencyProperty as the backing store for PxToMM.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PxToMMProperty =
            DependencyProperty.Register("PxToMM", typeof(double), typeof(VerticalTick), new PropertyMetadata(1.0, new PropertyChangedCallback(RefeshTick)));



        public double ImageY
        {
            get { return (double)GetValue(ImageYProperty); }
            set { SetValue(ImageYProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ImageY.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ImageYProperty =
            DependencyProperty.Register("ImageY", typeof(double), typeof(VerticalTick), new PropertyMetadata(0.0, new PropertyChangedCallback(RefeshTick)));



        public double ImagePxHeight
        {
            get { return (double)GetValue(ImagePxHeightProperty); }
            set { SetValue(ImagePxHeightProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ImagePxHeight.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ImagePxHeightProperty =
            DependencyProperty.Register("ImagePxHeight", typeof(double), typeof(VerticalTick), new PropertyMetadata(0.0, new PropertyChangedCallback(RefeshTick)));



        public Brush PenBrush
        {
            get { return (Brush)GetValue(PenBrushProperty); }
            set { SetValue(PenBrushProperty, value); }
        }

        // Using a DependencyProperty as the backing store for PenBrush.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PenBrushProperty =
            DependencyProperty.Register("PenBrush", typeof(Brush), typeof(VerticalTick), new PropertyMetadata(Brushes.White, (sender, e) =>
            {
                var dp = sender as VerticalTick;
                if (dp == null) return;
                dp.RefeshPen();
            }));



        public VerticalTick()
        {
            backpen = new Pen(PenBrush, 1);
            backpen.Freeze();
        }

        private void RefeshPen()
        {
            backpen = new Pen(PenBrush, 1);
            backpen.Freeze();
        }

        private static void RefeshTick(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var dp = d as VerticalTick;
            if (dp == null) return;
            dp.InvalidateVisual();
        }

        protected override void OnRender(DrawingContext drawingContext)
        {
            if (this.Visibility == Visibility.Collapsed) return;

            drawingContext.DrawLine(backpen, new Point(this.ActualWidth, 0), new Point(this.ActualWidth, this.ActualHeight));

            var x1y1 = new Point(rulerWidth, ImageY);

            int pycount = 0;
            double ImgH = ImagePxHeight * PxToMM;
            var scaleCount_Y = ImgH / scaleDefaultValue;
            var scalePx_Y = ImagePxHeight * ScaleValue / scaleCount_Y;
            if (scaleCount_Y > scaleMaxPx)
            {
                scaleDefaultValue = 1;
                scaleCount_Y = ImgH / scaleDefaultValue;
                scalePx_Y = ImagePxHeight * ScaleValue / scaleCount_Y;
            }
            if (scalePx_Y < scaleMinPx)
            {
                if (scaleDefaultValue == 1)
                {
                    scaleDefaultValue = 5;
                    scaleCount_Y = ImgH / scaleDefaultValue;
                    scalePx_Y = ImagePxHeight * ScaleValue / scaleCount_Y;
                }
                pycount = (int)(scaleMinPx / scalePx_Y);
            }
            int num_Y = 0;
            int scaleNum_Y = (int)((this.ActualHeight - x1y1.Y) / scalePx_Y) + 1;
            for (int i = 0; i < scaleNum_Y; i++)
            {
                if (pycount > 0)
                {
                    if (i % pycount != 0) continue;
                }

                var p0 = new Point(rulerWidth, scalePx_Y * i + x1y1.Y);
                var p1 = new Point(3 * rulerWidth / 4, scalePx_Y * i + x1y1.Y);
                var p2 = new Point(rulerWidth / 2, scalePx_Y * i + x1y1.Y);

                if (p0.Y >= rulerWidth)
                {
                    if (num_Y % 5 == 0)
                    {
                        drawingContext.DrawLine(backpen, p0, p2);
                        var txtvalue = Convert.ToInt32(i * scaleDefaultValue).ToString();
                        FormattedText txt = new FormattedText(txtvalue, new System.Globalization.CultureInfo("zh-CHS", false), FlowDirection.LeftToRight,
                            new Typeface("Microsoft YaHei"), 9, PenBrush);
                        RotateTransform rt = new RotateTransform(-90);
                        drawingContext.PushTransform(rt);
                        drawingContext.DrawText(txt, new Point(-(p2.Y + txt.Width / 2), p2.X - txt.Height));
                        drawingContext.Pop();
                    }
                    else
                    {
                        drawingContext.DrawLine(backpen, p0, p1);
                    }
                }
                num_Y++;
            }

            base.OnRender(drawingContext);
        }
    }
}
